package cc.shacocloud.mirage.utils.converter;

import org.jetbrains.annotations.NotNull;

/**
 * 转换器注册表
 * <p>
 * 转换器分为三个级别，匹配的顺序如下：
 * <ul>
 * <li>1. 指定源类型和目标类型进行精确转换 {@link #registry(TypeDescriptor, TypeDescriptor, Conversion)} </li>
 * <li>2. 指定目标类型进行转换 {@link #registry(TypeDescriptor, Conversion)} </li>
 * <li>3. 循环判断是否支持源类型到目标类型的转换 {@link #registry(ConversionSupport)} </li>
 * </ul>
 * <p>
 * 注意：该注册器一般来说 不是线程安全的，请不要在多线程场景中注册转换器
 *
 * @author 思追(shaco)
 * @see TypeConverterSupport
 */
public interface ConversionRegistry {
    
    /**
     * 注册指定来源和目标类型转换器
     * <p>
     * 该转换器优先匹配，如果没有匹配到则匹配 {@link #registry(Class, Conversion)} 注册的转换器
     *
     * @param sourceType 来源类型
     * @param targetType 目标类型
     * @param conversion 转换器
     */
    void registry(@NotNull TypeDescriptor sourceType, @NotNull TypeDescriptor targetType, @NotNull Conversion conversion);
    
    /**
     * 注册指定来源和目标类型转换器
     * <p>
     * 该转换器优先匹配，如果没有匹配到则匹配 {@link #registry(Class, Conversion)} 注册的转换器
     *
     * @see #registry(TypeDescriptor, TypeDescriptor, Conversion)
     */
    default void registry(@NotNull Class<?> sourceType, @NotNull Class<?> targetType, @NotNull Conversion conversion) {
        registry(TypeDescriptor.valueOf(sourceType), TypeDescriptor.valueOf(targetType), conversion);
    }
    
    /**
     * 注册目标类型转换器
     * <p>
     * 该转换器滞后匹配，如果 {@link #registry(TypeDescriptor, TypeDescriptor, Conversion)} 没有匹配到则进行匹配
     *
     * @param targetType 目标类型
     * @param conversion 转换器
     */
    void registry(@NotNull TypeDescriptor targetType, @NotNull Conversion conversion);
    
    /**
     * 注册目标类型转换器
     * <p>
     * 该转换器滞后匹配，如果 {@link #registry(TypeDescriptor, TypeDescriptor, Conversion)} 没有匹配到则进行匹配
     *
     * @see #registry(TypeDescriptor, Conversion)
     */
    default void registry(@NotNull Class<?> targetType, @NotNull Conversion conversion) {
        registry(TypeDescriptor.valueOf(targetType), conversion);
    }
    
    /**
     * 注册目标类型转换器
     * <p>
     * 该转换器最后匹配，如果 {@link #registry(TypeDescriptor, TypeDescriptor, Conversion)}和
     * {@link #registry(TypeDescriptor, Conversion)} 没有匹配到则进行匹配
     *
     * @param conversionSupport 转换器
     */
    void registry(@NotNull ConversionSupport conversionSupport);
    
}
